package com.tdf.webblog.handler;

import com.tdf.webblog.dao.*;
import com.tdf.webblog.dto.UserDTO;
import com.tdf.webblog.entity.*;
import com.tdf.webblog.service.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@RestController
public class UserProviderHandler {

    @Autowired
    private UserService userService;

    @Autowired
    private AdminRoleService adminRoleService;

    @Autowired
    private AdminPermissionService adminPermissionService;

    @Autowired
    private AdminMenuService adminMenuService;

    @Autowired
    private AdminRoleMenuService adminRoleMenuService;

    @Autowired
    private AdminRolePermissionDAO adminRolePermissionDAO;

    @Autowired
    private AdminPermissionDAO adminPermissionDAO;

    @Autowired
    private UserDAO userDAO;

    @Autowired
    private AdminRoleDAO adminRoleDAO;

    @Autowired
    private AdminMenuDAO adminMenuDAO;


    @RequestMapping("/find/by/username/remote")
    public User findByUsernameRemote(@RequestParam("username") String username){

        return userService.findByUsername(username);
    }

    @RequestMapping("/listpermissionurls/by/user/remote")
    public Set<String> listPermissionURLsByUserRemote(@RequestParam("username") String username){



        List<Integer> rids = adminRoleService.listRolesByUser(username)
                .stream().map(AdminRole::getId).collect(Collectors.toList());

        List<Integer> pids = adminRolePermissionDAO.findAllByRid(rids)
                .stream().map(AdminRolePermission::getPid).collect(Collectors.toList());

        List<AdminPermission> perms = adminPermissionDAO.findAllById(pids);

        Set<String> URLs = perms.stream().map(AdminPermission::getUrl).collect(Collectors.toSet());

        return URLs;
    }

    @RequestMapping("/find/all/remote")
    public List<AdminPermission> findAllRemote(){
        return adminPermissionDAO.findAll();
    }

    @RequestMapping("/list/remote")
    public List<UserDTO> listRemote(){
        List<User> users = userDAO.findAll();
        // Find all roles in DB to enable JPA persistence context.
        //List<AdminRole> allRoles = adminRoleService.findAll();

        List<UserDTO> userDTOS = users
                .stream().map(user -> (UserDTO) new UserDTO().convertFrom(user)).collect(Collectors.toList());

        userDTOS.forEach(u -> {
            List<AdminRole> roles = adminRoleService.listRolesByUser(u.getUsername());
            u.setRoles(roles);
        });
        return userDTOS;
    }

    @PostMapping("save/user/remote")
    int saveUserRemote(@RequestBody User user){
        return userService.saveUser(user);
    }

    @GetMapping("list/with/perms/and/menus/remote")
    public List<AdminRole> listWithPermsAndMenusRemote(){
        List<AdminRole> roles = adminRoleDAO.findAll();
        List<AdminPermission> perms;
        List<AdminMenu> menus;
        for (AdminRole role : roles) {
            perms = adminPermissionService.listPermsByRoleId(role.getId());
            menus = adminMenuService.getMenusByRoleId(role.getId());
            role.setPerms(perms);
            role.setMenus(menus);
        }
        return roles;
    }

    @GetMapping("/get/menus/by/roleid/remote")
    public List<AdminMenu> getMenusByRoleIdRemote(@RequestParam("i") int rid){
        List<Integer> menuIds = adminRoleMenuService.findAllByRid(rid)
                .stream().map(AdminRoleMenu::getMid).collect(Collectors.toList());
        List<AdminMenu> menus = adminMenuDAO.findAllById(menuIds);

        handleMenus(menus);
        return menus;
    }

    @GetMapping("/admin/role/perm")
    List<AdminPermission> listAdminPermissionRemote(){
        return adminPermissionDAO.findAll();
    }

    /**
     * Adjust the Structure of the menu.
     *
     * @param menus Menu items list without structure
     */
    public void handleMenus(List<AdminMenu> menus) {
        menus.forEach(m -> {
            List<AdminMenu> children = getAllByParentId(m.getId());
            m.setChildren(children);
        });

        menus.removeIf(m -> m.getParentId() != 0);
    }
    public List<AdminMenu> getAllByParentId(int parentId) {
        return adminMenuDAO.findAllByParentId(parentId);
    }

}
